using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using OpcUaHelper;
using WIT.DAQ.Core.Helper;
using WIT.DAQ.Core.Models;

namespace WIT.DAQ.Core.Forms;

/// <summary>
/// 结构体/数组详情监控界面
/// </summary>
internal class DetailForm : BaseForm
{
	/// <summary>
	/// 设备
	/// </summary>
	private Device DEVICE;

	/// <summary>
	/// OPCUA连接实例
	/// </summary>
	private OpcUaClient OPCUACONNECTION;

	/// <summary>
	/// 采集项
	/// </summary>
	private DAQItem DAQITEM;

	/// <summary>
	/// 异步监控采集项
	/// </summary>
	private BackgroundWorker BW_MONITORDAQITEM;

	/// <summary>
	/// 异步监控的频率
	/// </summary>
	private int INTERVAL = 1000;

	/// <summary>
	/// Required designer variable.
	/// </summary>
	private IContainer components = null;

	private TreeView tvProperties;

	private ContextMenuStrip cmsProperty;

	private ToolStripMenuItem tsmiWriteValue;

	private ToolStripMenuItem tsmiExpandAll;

	private ToolStripMenuItem tsmiCollapseAll;

	private ToolStripMenuItem tsmiExpand;

	private ToolStripMenuItem tsmiCollapse;

	private ToolStripSeparator tsSeparator;

	/// <summary>
	///
	/// </summary>
	/// <param name="device">设备</param>
	/// <param name="opcuaConnection">OPCUA连接实例</param>
	/// <param name="daqItem">采集项</param>
	/// <param name="interval">监控频率ms</param>
	/// <param name="value">数据实例</param>
	internal DetailForm(Device device, OpcUaClient opcuaConnection, DAQItem daqItem, int interval, object value)
	{
		InitializeComponent();
		DEVICE = device;
		OPCUACONNECTION = opcuaConnection;
		DAQITEM = daqItem;
		INTERVAL = interval;
		Text = daqItem.Name + " " + DAQITEM.NodeId;
		Type type = value.GetType();
		string empty = string.Empty;
		empty = ((!daqItem.NodeId.Contains(".")) ? daqItem.NodeId.Substring(daqItem.NodeId.IndexOf(";s=") + 3).Replace("\"", "") : daqItem.NodeId.Substring(daqItem.NodeId.LastIndexOf(".") + 1).Replace("\"", ""));
		TreeNode treeNode = new TreeNode
		{
			Name = daqItem.NodeId,
			Text = "[" + type.Name + "] " + empty,
			Tag = value
		};
		RecursiveCreateTreeNodes(treeNode);
		tvProperties.Nodes.Add(treeNode);
	}

	private void DetailForm_Load(object sender, EventArgs e)
	{
		BW_MONITORDAQITEM = new BackgroundWorker
		{
			WorkerSupportsCancellation = true
		};
		BW_MONITORDAQITEM.DoWork += MonitorDAQItem;
		BW_MONITORDAQITEM.RunWorkerAsync();
	}

	/// <summary>
	/// 递归创建Tree结构
	/// </summary>
	/// <param name="parentNode"></param>
	private void RecursiveCreateTreeNodes(TreeNode parentNode)
	{
		object tag = parentNode.Tag;
		Type type = tag.GetType();
		if (tag is IList)
		{
			List<object> list = new List<object>();
			Type type2 = tag.GetType();
			if (type2 == typeof(List<short>))
			{
				foreach (short item in (List<short>)tag)
				{
					list.Add(item);
				}
			}
			else if (type2 == typeof(List<int>))
			{
				foreach (int item2 in (List<int>)tag)
				{
					list.Add(item2);
				}
			}
			else if (type2 == typeof(List<long>))
			{
				foreach (long item3 in (List<long>)tag)
				{
					list.Add(item3);
				}
			}
			else if (type2 == typeof(List<ushort>))
			{
				foreach (ushort item4 in (List<ushort>)tag)
				{
					list.Add(item4);
				}
			}
			else if (type2 == typeof(List<uint>))
			{
				foreach (uint item5 in (List<uint>)tag)
				{
					list.Add(item5);
				}
			}
			else if (type2 == typeof(List<ulong>))
			{
				foreach (ulong item6 in (List<ulong>)tag)
				{
					list.Add(item6);
				}
			}
			else if (type2 == typeof(List<bool>))
			{
				foreach (bool item7 in (List<bool>)tag)
				{
					list.Add(item7);
				}
			}
			else if (type2 == typeof(List<byte>))
			{
				foreach (byte item8 in (List<byte>)tag)
				{
					list.Add(item8);
				}
			}
			else if (type2 == typeof(List<float>))
			{
				foreach (float item9 in (List<float>)tag)
				{
					list.Add(item9);
				}
			}
			else if (type2 == typeof(List<double>))
			{
				foreach (double item10 in (List<double>)tag)
				{
					list.Add(item10);
				}
			}
			else if (type2 == typeof(List<DateTime>))
			{
				foreach (DateTime item11 in (List<DateTime>)tag)
				{
					list.Add(item11);
				}
			}
			else if (type2 == typeof(List<string>))
			{
				foreach (string item12 in (List<string>)tag)
				{
					list.Add(item12);
				}
			}
			else
			{
				list = (List<object>)tag;
			}
			for (int i = 0; i < list.Count; i++)
			{
				Type type3 = list[i].GetType();
				string empty = string.Empty;
				empty = ((!parentNode.Name.Contains(".")) ? parentNode.Name.Substring(parentNode.Name.IndexOf(";s=") + 3).Trim('"') : parentNode.Name.Substring(parentNode.Name.LastIndexOf(".") + 1).Trim('"'));
				TreeNode treeNode = new TreeNode
				{
					Name = $"{parentNode.Name}[{i}]",
					Tag = list[i]
				};
				if (!type3.IsValueType && type3 != typeof(string))
				{
					treeNode.Text = $"[{type3.Name}] {empty}[{i}]";
					RecursiveCreateTreeNodes(treeNode);
				}
				else
				{
					treeNode.Text = $"[{type3.Name}] {empty}[{i}]:{list[i]}";
				}
				parentNode.Nodes.Add(treeNode);
			}
			return;
		}
		PropertyInfo[] properties = type.GetProperties();
		foreach (PropertyInfo propertyInfo in properties)
		{
			object value = DynamicClassHelper.GetValue(type, tag, propertyInfo.Name);
			Type type4 = value.GetType();
			TreeNode treeNode2 = new TreeNode
			{
				Name = parentNode.Name + "." + propertyInfo.Name,
				Tag = value
			};
			if (!type4.IsValueType && type4 != typeof(string))
			{
				treeNode2.Text = "[" + type4.Name + "] " + propertyInfo.Name;
				RecursiveCreateTreeNodes(treeNode2);
			}
			else
			{
				treeNode2.Text = $"[{type4.Name}] {propertyInfo.Name}:{value}";
			}
			parentNode.Nodes.Add(treeNode2);
		}
	}

	/// <summary>
	/// 异步监控
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void MonitorDAQItem(object sender, DoWorkEventArgs e)
	{
		BackgroundWorker backgroundWorker = (BackgroundWorker)sender;
		List<object> values;
		Exception ex;
		while (!backgroundWorker.CancellationPending && !backgroundWorker.CancellationPending)
		{
			try
			{
				if (backgroundWorker.CancellationPending)
				{
					break;
				}
				if (!Common.ReadValues(OPCUACONNECTION, DEVICE, new List<DAQItem> { DAQITEM }, out values, out var errMsg))
				{
					throw new Exception(errMsg);
				}
				Invoke((Action)delegate
				{
					TreeNode treeNode = tvProperties.Nodes[0];
					if (values[0] != treeNode.Tag)
					{
						Type type = values[0].GetType();
						string empty = string.Empty;
						treeNode.Text = string.Concat(str3: (!treeNode.Name.Contains(".")) ? treeNode.Name.Substring(treeNode.Name.IndexOf(";s=") + 3).Replace("\"", "") : treeNode.Name.Substring(treeNode.Name.LastIndexOf(".") + 1).Replace("\"", ""), str0: "[", str1: type.Name, str2: "] ");
						treeNode.Tag = values[0];
						tvProperties.BeginUpdate();
						RecursiveUpdateTreeNodes(treeNode);
						tvProperties.EndUpdate();
					}
				});
			}
			catch (Exception ex2)
			{
				ex = ex2;
				if (!backgroundWorker.CancellationPending)
				{
					try
					{
						Invoke((Action)delegate
						{
							tvProperties.Nodes[0].Text = ex.Message;
							tvProperties.BeginUpdate();
							RecursiveSetNodesText(tvProperties.Nodes[0], ex.Message);
							tvProperties.EndUpdate();
						});
					}
					catch
					{
						break;
					}
				}
			}
			Thread.Sleep(INTERVAL);
		}
	}

	/// <summary>
	/// 递归给TreeNode更新值
	/// </summary>
	/// <param name="parentNode"></param>
	private void RecursiveUpdateTreeNodes(TreeNode parentNode)
	{
		if (BW_MONITORDAQITEM.CancellationPending)
		{
			return;
		}
		object tag = parentNode.Tag;
		Type type = tag.GetType();
		if (tag is IList)
		{
			List<object> list = new List<object>();
			Type type2 = tag.GetType();
			if (type2 == typeof(List<short>))
			{
				foreach (short item in (List<short>)tag)
				{
					list.Add(item);
				}
			}
			else if (type2 == typeof(List<int>))
			{
				foreach (int item2 in (List<int>)tag)
				{
					list.Add(item2);
				}
			}
			else if (type2 == typeof(List<long>))
			{
				foreach (long item3 in (List<long>)tag)
				{
					list.Add(item3);
				}
			}
			else if (type2 == typeof(List<ushort>))
			{
				foreach (ushort item4 in (List<ushort>)tag)
				{
					list.Add(item4);
				}
			}
			else if (type2 == typeof(List<uint>))
			{
				foreach (uint item5 in (List<uint>)tag)
				{
					list.Add(item5);
				}
			}
			else if (type2 == typeof(List<ulong>))
			{
				foreach (ulong item6 in (List<ulong>)tag)
				{
					list.Add(item6);
				}
			}
			else if (type2 == typeof(List<bool>))
			{
				foreach (bool item7 in (List<bool>)tag)
				{
					list.Add(item7);
				}
			}
			else if (type2 == typeof(List<byte>))
			{
				foreach (byte item8 in (List<byte>)tag)
				{
					list.Add(item8);
				}
			}
			else if (type2 == typeof(List<float>))
			{
				foreach (float item9 in (List<float>)tag)
				{
					list.Add(item9);
				}
			}
			else if (type2 == typeof(List<double>))
			{
				foreach (double item10 in (List<double>)tag)
				{
					list.Add(item10);
				}
			}
			else if (type2 == typeof(List<DateTime>))
			{
				foreach (DateTime item11 in (List<DateTime>)tag)
				{
					list.Add(item11);
				}
			}
			else if (type2 == typeof(List<string>))
			{
				foreach (string item12 in (List<string>)tag)
				{
					list.Add(item12);
				}
			}
			else
			{
				list = (List<object>)tag;
			}
			if (list.Count != parentNode.Nodes.Count)
			{
				RecursiveSetNodesText(parentNode, "数组长度发生了变化");
				return;
			}
			string empty = string.Empty;
			empty = ((!parentNode.Name.Contains(".")) ? parentNode.Name.Substring(parentNode.Name.IndexOf(";s=") + 3).Trim('"') : parentNode.Name.Substring(parentNode.Name.LastIndexOf(".") + 1).Trim('"'));
			for (int i = 0; i < parentNode.Nodes.Count; i++)
			{
				if (BW_MONITORDAQITEM.CancellationPending)
				{
					break;
				}
				parentNode.Nodes[i].Tag = list[i];
				if (parentNode.Nodes[i].Nodes.Count > 0)
				{
					parentNode.Nodes[i].Text = $"[{list[0].GetType().Name}] {empty}[{i}]";
					RecursiveUpdateTreeNodes(parentNode.Nodes[i]);
					continue;
				}
				parentNode.Nodes[i].Text = $"[{list[0].GetType().Name}] {empty}[{i}]:{list[i]}";
			}
			return;
		}
		foreach (TreeNode node in parentNode.Nodes)
		{
			if (BW_MONITORDAQITEM.CancellationPending)
			{
				break;
			}
			string text = node.Name.Substring(node.Name.IndexOf(parentNode.Name) + parentNode.Name.Length + 1);
			object obj = null;
			try
			{
				obj = DynamicClassHelper.GetValue(type, tag, text);
			}
			catch
			{
				node.Text = "BadNodeIdUnknown";
				node.Tag = null;
				continue;
			}
			if (obj != node.Tag)
			{
				node.Tag = obj;
				if (node.Nodes.Count > 0)
				{
					node.Text = "[" + obj.GetType().Name + "] " + text;
					RecursiveUpdateTreeNodes(node);
				}
				else
				{
					node.Text = $"[{obj.GetType().Name}] {text}:{obj}";
				}
			}
		}
	}

	/// <summary>
	/// 给TreeView指定节点下的所有子节点赋相同值
	/// </summary>
	/// <param name="parentNode"></param>
	/// <param name="text"></param>
	private void RecursiveSetNodesText(TreeNode parentNode, string text)
	{
		foreach (TreeNode node in parentNode.Nodes)
		{
			node.Text = text;
			node.Tag = null;
			RecursiveSetNodesText(node, text);
		}
	}

	/// <summary>
	/// 右键动态展示不同的菜单
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tvProperties_MouseDown(object sender, MouseEventArgs e)
	{
		if (e.Button != MouseButtons.Right)
		{
			return;
		}
		tvProperties.ContextMenuStrip = cmsProperty;
		Point pt = new Point(e.X, e.Y);
		TreeNode nodeAt = tvProperties.GetNodeAt(pt);
		if (nodeAt != null)
		{
			tvProperties.SelectedNode = nodeAt;
			if (nodeAt.Tag == null)
			{
				return;
			}
			Type type = tvProperties.SelectedNode.Tag.GetType();
			tsmiWriteValue.Visible = type.IsValueType || type == typeof(string);
			if (tvProperties.SelectedNode.Nodes.Count > 0)
			{
				if (tvProperties.SelectedNode.IsExpanded)
				{
					tsmiExpand.Visible = false;
					tsmiCollapse.Visible = true;
				}
				else
				{
					tsmiExpand.Visible = true;
					tsmiCollapse.Visible = false;
				}
			}
			else
			{
				tsmiExpand.Visible = false;
				tsmiCollapse.Visible = false;
			}
			tsSeparator.Visible = true;
			tsmiExpandAll.Visible = true;
			tsmiCollapseAll.Visible = true;
		}
		else
		{
			tsmiWriteValue.Visible = false;
			tsmiExpand.Visible = false;
			tsmiCollapse.Visible = false;
			tsSeparator.Visible = false;
			tsmiExpandAll.Visible = true;
			tsmiCollapseAll.Visible = true;
			tvProperties.SelectedNode = null;
		}
	}

	/// <summary>
	/// 左键双击时，写入值
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tvProperties_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
	{
		if (e.Button == MouseButtons.Left)
		{
			tsmiWriteValue_Click(null, null);
		}
	}

	/// <summary>
	/// 右键菜单-写入值
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tsmiWriteValue_Click(object sender, EventArgs e)
	{
		if (tvProperties.SelectedNode != null && tvProperties.SelectedNode.Tag != null)
		{
			Type type = tvProperties.SelectedNode.Tag.GetType();
			if (type.IsValueType || type == typeof(string))
			{
				DAQItem daqItem = new DAQItem
				{
					DeviceId = DEVICE.Id,
					DataType = type.Name,
					NodeId = tvProperties.SelectedNode.Name
				};
				TreeNode selectedNode = tvProperties.SelectedNode;
				string text = selectedNode.Name.Substring(selectedNode.Name.IndexOf(selectedNode.Parent.Name) + selectedNode.Parent.Name.Length + 1);
				string text2 = text + ":";
				string defaultValue = selectedNode.Text.Substring(selectedNode.Text.IndexOf(text2) + text2.Length);
				WriteValueForm writeValueForm = new WriteValueForm(DEVICE, daqItem, defaultValue, OPCUACONNECTION)
				{
					Icon = base.Icon,
					StartPosition = FormStartPosition.CenterParent
				};
				writeValueForm.ShowDialog();
			}
		}
	}

	/// <summary>
	/// 展开全部节点
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tsmiExpandAll_Click(object sender, EventArgs e)
	{
		tvProperties.ExpandAll();
	}

	/// <summary>
	/// 折叠全部节点
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tsmiCollapseAll_Click(object sender, EventArgs e)
	{
		tvProperties.CollapseAll();
	}

	/// <summary>
	/// 展开节点
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tsmiExpand_Click(object sender, EventArgs e)
	{
		tvProperties.SelectedNode.Expand();
	}

	/// <summary>
	/// 折叠节点
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void tsmiCollapse_Click(object sender, EventArgs e)
	{
		tvProperties.SelectedNode.Collapse();
	}

	private void DetailForm_FormClosing(object sender, FormClosingEventArgs e)
	{
		BW_MONITORDAQITEM.CancelAsync();
	}

	/// <summary>
	/// ESC关闭
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void DetailForm_KeyDown(object sender, KeyEventArgs e)
	{
		if (e.KeyCode == Keys.Escape)
		{
			Close();
		}
	}

	/// <summary>
	/// Clean up any resources being used.
	/// </summary>
	/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
	protected override void Dispose(bool disposing)
	{
		if (disposing && components != null)
		{
			components.Dispose();
		}
		base.Dispose(disposing);
	}

	/// <summary>
	/// Required method for Designer support - do not modify
	/// the contents of this method with the code editor.
	/// </summary>
	private void InitializeComponent()
	{
		this.components = new System.ComponentModel.Container();
		this.tvProperties = new System.Windows.Forms.TreeView();
		this.cmsProperty = new System.Windows.Forms.ContextMenuStrip(this.components);
		this.tsmiWriteValue = new System.Windows.Forms.ToolStripMenuItem();
		this.tsmiCollapse = new System.Windows.Forms.ToolStripMenuItem();
		this.tsmiExpand = new System.Windows.Forms.ToolStripMenuItem();
		this.tsSeparator = new System.Windows.Forms.ToolStripSeparator();
		this.tsmiExpandAll = new System.Windows.Forms.ToolStripMenuItem();
		this.tsmiCollapseAll = new System.Windows.Forms.ToolStripMenuItem();
		this.cmsProperty.SuspendLayout();
		base.SuspendLayout();
		this.tvProperties.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
		this.tvProperties.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
		this.tvProperties.ItemHeight = 15;
		this.tvProperties.Location = new System.Drawing.Point(4, 7);
		this.tvProperties.Name = "tvProperties";
		this.tvProperties.ShowNodeToolTips = true;
		this.tvProperties.Size = new System.Drawing.Size(496, 551);
		this.tvProperties.TabIndex = 7;
		this.tvProperties.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(tvProperties_NodeMouseDoubleClick);
		this.tvProperties.MouseDown += new System.Windows.Forms.MouseEventHandler(tvProperties_MouseDown);
		this.cmsProperty.Items.AddRange(new System.Windows.Forms.ToolStripItem[6] { this.tsmiWriteValue, this.tsmiCollapse, this.tsmiExpand, this.tsSeparator, this.tsmiExpandAll, this.tsmiCollapseAll });
		this.cmsProperty.Name = "cmsProperties";
		this.cmsProperty.Size = new System.Drawing.Size(133, 120);
		this.tsmiWriteValue.Name = "tsmiWriteValue";
		this.tsmiWriteValue.Size = new System.Drawing.Size(132, 22);
		this.tsmiWriteValue.Text = "写入值(&W)";
		this.tsmiWriteValue.Click += new System.EventHandler(tsmiWriteValue_Click);
		this.tsmiCollapse.Name = "tsmiCollapse";
		this.tsmiCollapse.Size = new System.Drawing.Size(132, 22);
		this.tsmiCollapse.Text = "折叠";
		this.tsmiCollapse.Click += new System.EventHandler(tsmiCollapse_Click);
		this.tsmiExpand.Name = "tsmiExpand";
		this.tsmiExpand.Size = new System.Drawing.Size(132, 22);
		this.tsmiExpand.Text = "展开";
		this.tsmiExpand.Click += new System.EventHandler(tsmiExpand_Click);
		this.tsSeparator.Name = "tsSeparator";
		this.tsSeparator.Size = new System.Drawing.Size(129, 6);
		this.tsmiExpandAll.Name = "tsmiExpandAll";
		this.tsmiExpandAll.Size = new System.Drawing.Size(132, 22);
		this.tsmiExpandAll.Text = "全部展开";
		this.tsmiExpandAll.Click += new System.EventHandler(tsmiExpandAll_Click);
		this.tsmiCollapseAll.Name = "tsmiCollapseAll";
		this.tsmiCollapseAll.Size = new System.Drawing.Size(132, 22);
		this.tsmiCollapseAll.Text = "全部折叠";
		this.tsmiCollapseAll.Click += new System.EventHandler(tsmiCollapseAll_Click);
		base.AutoScaleDimensions = new System.Drawing.SizeF(6f, 12f);
		base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
		base.ClientSize = new System.Drawing.Size(504, 561);
		base.Controls.Add(this.tvProperties);
		base.MinimizeBox = false;
		this.MinimumSize = new System.Drawing.Size(300, 400);
		base.Name = "DetailForm";
		this.Text = "明细数据";
		base.FormClosing += new System.Windows.Forms.FormClosingEventHandler(DetailForm_FormClosing);
		base.Load += new System.EventHandler(DetailForm_Load);
		base.KeyDown += new System.Windows.Forms.KeyEventHandler(DetailForm_KeyDown);
		this.cmsProperty.ResumeLayout(false);
		base.ResumeLayout(false);
	}
}
